#include "bootpack.h"
/*gdt idt 的初始化*/
/***********************************************************************************************
***********************************************************************************************/
void init_gdtidt(void)
{
	//变量gdt被赋值0x00270000，就是说要将0x270000～0x27ffff设为GDT。
	struct SEGMENT_DESCRIPTOR *gdt = (struct SEGMENT_DESCRIPTOR *)0x00270000;
	//IDT被设为了0x26f800～0x26ffff
	struct GATE_DESCRIPTOR *idt = (struct GATE_DESCRIPTOR *)0x0026f800;
	int i;

	/* GDT的初期化 */
	//	完成了对所有8192个段的设定，将它们的上限
	//（limit, 指段的字节数-1）、基址（base）、访问权限都设为0。
	for (i = 0; i < 8192; i++)
	{
		set_segmdesc(gdt + i, 0, 0, 0);
	}


	set_segmdesc(gdt + 1, 0xffffffff, 0x00000000, 0x4092); // 全部内存本身
	set_segmdesc(gdt + 2, 0x0007ffff, 0x00280000, 0x409a); // 这是为bootpack.hrb而准备的。
	load_gdtr(0xffff, 0x00270000);	//载入gdtr

	/* IDT的初期化 */
	for (i = 0; i < 256; i++)
	{
		set_gatedesc(idt + i, 0, 0, 0);
	}
	load_idtr(0x7ff, 0x0026f800);
	/* IDT 的设定*/
	set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
	return;
}
/*对于 gdt的中一个段号的设定*/
/***********************************************************************************************
 sd-段号所在的地址 limit-上限（ 指段的字节数-1）base-基址 ar-访问权限
***********************************************************************************************/
void set_segmdesc(struct SEGMENT_DESCRIPTOR *sd, unsigned int limit, int base, int ar)
{
	if (limit > 0xfffff)
	{
		ar |= 0x8000; /* G_bit = 1 */
		limit /= 0x1000;
	}
	sd->limit_low = limit & 0xffff;
	sd->base_low = base & 0xffff;
	sd->base_mid = (base >> 16) & 0xff;
	sd->access_right = ar & 0xff;
	sd->limit_high = ((limit >> 16) & 0x0f) | ((ar >> 8) & 0xf0);
	sd->base_high = (base >> 24) & 0xff;
	return;
}

void set_gatedesc(struct GATE_DESCRIPTOR *gd, int offset, int selector, int ar)
{
	gd->offset_low = offset & 0xffff;
	gd->selector = selector;
	gd->dw_count = (ar >> 8) & 0xff;
	gd->access_right = ar & 0xff;
	gd->offset_high = (offset >> 16) & 0xffff;
	return;
}
